// Xampler, a MIDI-driven sampler
// Copyright (C) 2006 Nick Thomas
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
// 02110-1301 USA.

#ifndef XAMPLER_SAMPLE_HPP
#define XAMPLER_SAMPLE_HPP

// Holds a single sample's sample data and volume/balance
// settings. See also Instrument.hpp
//
// These objects are read and written concurrently by the synthesis
// thread and the UI thread. This is risk-free for the atomic values
// (volume and balance), but can potentially cause race conditions
// when the UI thread loads a new sample from a file, if the synthesis
// thread happens to access the sample at the right moment. This bug
// is sufficiently rare and difficult to fix that it may be left
// unfixed.

#include <glibmm/object.h>

namespace xampler
{
    const double MAX_VOLUME = 1.2;
    const double DEFAULT_VOLUME = 0.8;

    class Sample
    {
    public:
        Sample();

        int get_number() { return m_number; }
        void set_number(int number) { m_number = number; }

        Glib::ustring get_name() { return m_name; }
        void set_name(Glib::ustring name) { m_name = name; }

        double get_volume() { return m_volume; }
        void set_volume(double volume) { m_volume = volume; }

        double get_balance() { return m_balance; }
        void set_balance(double balance) { m_balance = balance; }

        Glib::ustring get_filename() { return m_filename; }

        // Attempts to load the given sound file using libsndfile,
        // returning true on success and false on failure.
        bool load_data(Glib::ustring filename, Glib::ustring &error);

        int get_num_frames() { return m_num_frames; }
        float *get_left_channel() { return m_left_channel; }
        float *get_right_channel() { return m_right_channel; }

        // Returns true if the sample contains no data, and false otherwise.
        bool is_empty() { return m_num_frames == 0; }

    private:
        int m_number;
        Glib::ustring m_name;
        double m_volume;
        double m_balance;
        Glib::ustring m_filename;

        int m_num_frames;
        float *m_left_channel;
        float *m_right_channel;
    };
}

#endif
